package org.pray.reversedep;

import java.util.Date;

/**
 * @author Rainy 单例模式
 * @since 2024/3/10
 * 单例模式
 */
public class DependWithSingleMode extends DependenceReverse {

    private static Long instanceTime;//记录实例创建的时间
    public Long getInstanceTime() {
        return instanceTime;
    }

    public static void setInstanceTime(Long instance) {
        instanceTime=instance;
    }

    private DependWithSingleMode() {
        //System.out.println("懒汉式单例初始化！");
        synchronized (DependWithSingleMode.class) {
            if(Instance != null){
                throw new RuntimeException("单例构造器禁止反射调用");
            }
        }
    };

    //懒汉式加载，可能存在线程竞争
    //加上volatile关键字禁止指令重排
    private  static  volatile DependWithSingleMode Instance;

    //饿汉式加载，饿汉式是线程安全的，因为实例对象已经在类加载时就创建好了，不存在多线程环境下的竞争问题。
    private static DependWithSingleMode eagerInstance=new DependWithSingleMode();
    public static DependWithSingleMode getEagerInstance(){
        return eagerInstance;
    }


    //下面的都是懒汉式加载

    //1.单线程单例模式（有缺陷），存在竞争
    public static DependWithSingleMode getInstance() {
        if (Instance == null) {
            long time = new Date().getTime();
            setInstanceTime(time);
            System.out.println("实例化时间："+time);
            Instance = new DependWithSingleMode();
        }
        return Instance;
    }

    //2.synchronized只能保证有序性，但无法禁止指令重排
    public static DependWithSingleMode getInstanceWithLock() {
        //加锁，一定程度上防止多线程造成多个实例创建，性能下降很多
        synchronized (DependWithSingleMode.class){
            if (Instance == null) {
                long time = new Date().getTime();
                setInstanceTime(time);
                System.out.println("实例化时间："+time);
                Instance = new DependWithSingleMode();
            }
            return Instance;
        }
    }

    /**
     * 双判断锁
     * @
     * return
     */
    //3.双判断
    public static DependWithSingleMode getInstanceWithPredicate(){
        if (Instance==null){
            synchronized (DependWithSingleMode.class){
                //再次 判断，假如别的线程创建了就直接返回，否则进入创建
                if (Instance==null){
                    long time = new Date().getTime();
                    setInstanceTime(time);
                    System.out.println("实例化时间："+time);
                    Instance = new DependWithSingleMode();
                }
                else {
                    return Instance;
                }
            }
        }
        return Instance;
    }
    //4.通过匿名内部类实现单例模式

    private static class ProduceInstance{
        //由静态内部类持有单例对象，但是根据类加载特性，我们仅使用Singleton类时，不会对静态内部类进行初始化
        private final static  DependWithSingleMode INCETANCE =new DependWithSingleMode();

    }
    public static DependWithSingleMode getInstanceWithInnerClass(){
        return ProduceInstance.INCETANCE;
    }
    @Override
    void methodWithAbstract() {
        System.out.println("子类继承时实现的方法");
    }
}
